home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / hydra / amiga.c < prev    next >
C/C++ Source or Header  |  1995-12-20  |  41KB  |  1,860 lines

  1. /*
  2. **    Amiga support module for HYDRA protocol sample implementation.
  3. **
  4. **    Written by    Olaf Barthel
  5. **            Brabeckstrasse 35
  6. **            D-30559 Hannover
  7. **
  8. **            eMail: olsen@sourcery.han.de
  9. **
  10. **    Freely distributable.
  11. */
  12.  
  13.     /* System includes. */
  14.  
  15. #include <intuition/intuitionbase.h>
  16.  
  17. #include <libraries/gadtools.h>
  18.  
  19. #include <graphics/gfxbase.h>
  20.  
  21. #include <utility/date.h>
  22.  
  23. #include <devices/conunit.h>
  24. #include <devices/serial.h>
  25. #include <devices/timer.h>
  26.  
  27. #include <hardware/cia.h>
  28.  
  29. #include <dos/dosextens.h>
  30. #include <dos/filehandler.h>
  31. #include <dos/dosasl.h>
  32.  
  33. #include <exec/memory.h>
  34.  
  35.     /* Correct a nasty bug in the prototypes. */
  36.  
  37. #define CheckIO foo21234
  38.  
  39. #include <clib/intuition_protos.h>
  40. #include <clib/gadtools_protos.h>
  41. #include <clib/graphics_protos.h>
  42. #include <clib/utility_protos.h>
  43. #include <clib/timer_protos.h>
  44. #include <clib/exec_protos.h>
  45. #include <clib/dos_protos.h>
  46. #include <clib/macros.h>
  47.  
  48.     /* Get the CheckIO prototype right. */
  49.  
  50. #undef CheckIO
  51.  
  52. struct IORequest *CheckIO(struct IORequest *);
  53.  
  54. #include "Rendezvous.h"
  55.  
  56. #include "hydracom.h"
  57.  
  58.     /* Serial buffer size. */
  59.  
  60. #define BUFFER_SIZE 8192
  61.  
  62.     /* A handy macro. */
  63.  
  64. #define ClrSignal(s)    SetSignal(0,s)
  65.  
  66.     /* Signal masks. */
  67.  
  68. #define SIG_SERREAD    (1UL << ReadPort -> mp_SigBit)
  69. #define SIG_SERWRITE    (1UL << WritePort -> mp_SigBit)
  70. #define SIG_CONREAD    (1UL << ConsoleReadPort -> mp_SigBit)
  71. #define SIG_TIMER    (1UL << TimePort -> mp_SigBit)
  72. #define SIG_WINDOW    (1UL << LocalWindow -> UserPort -> mp_SigBit)
  73.  
  74.     /* A serial buffer structure. */
  75.  
  76. struct SerialBuffer
  77. {
  78.     struct IOExtSer    *SerialRequest;
  79.     UBYTE        *SerialBuffer,
  80.             *SerialIndex,
  81.             *SerialTop;
  82.     LONG         SerialSize,
  83.              SerialFilled;
  84.     BOOL         IsClone,
  85.              IsBusy;
  86. };
  87.  
  88. STATIC struct RendezvousData        *RendezvousData;
  89. STATIC struct RendezvousSemaphore    *RendezvousSemaphore;
  90.  
  91.     /* Library bases. */
  92.  
  93. struct IntuitionBase    *IntuitionBase;
  94. struct GfxBase        *GfxBase;
  95. struct Library        *GadToolsBase,
  96.             *UtilityBase,
  97.             *TimerBase;
  98.  
  99.     /* Timer data. */
  100.  
  101. struct MsgPort        *TimePort;
  102. struct timerequest    *TimeRequest;
  103.  
  104.     /* Serial data. */
  105.  
  106. struct MsgPort        *ReadPort,
  107.             *WritePort;
  108.  
  109. struct SerialBuffer    *ThisBuffer,
  110.             *NextBuffer,
  111.             *ReadBuffer;
  112.  
  113.     /* Console data. */
  114.  
  115. struct Window        *FileWindow,
  116.             *RemoteWindow,
  117.             *LocalWindow,
  118.             *LogWindow;
  119.  
  120. struct MsgPort        *ConsoleWritePort,
  121.             *ConsoleReadPort;
  122. struct IOStdReq        *ConsoleReadRequest;
  123. UBYTE             ConsoleChar;
  124. BOOL             ConsoleReady = FALSE,
  125.              WindowReady = FALSE;
  126.  
  127. struct IOStdReq        *FileRequest,
  128.             *RemoteRequest,
  129.             *LocalRequest,
  130.             *LogRequest;
  131.  
  132.     /* DOS Data. */
  133.  
  134. struct Process        *ThisProcess;
  135. APTR             OldPtr;
  136.  
  137. struct AnchorPath    *Anchor;
  138. BOOL             AnchorUsed = FALSE;
  139.  
  140.     /* Screen data. */
  141.  
  142. struct Screen        *PublicScreen,
  143.             *Screen;
  144.  
  145.     /* Menu data. */
  146.  
  147. APTR             VisualInfo;
  148. struct Menu        *Menu;
  149.  
  150. struct NewMenu MenuTemplate[] =
  151. {
  152.     { NM_TITLE, "Project",             0 ,    0,    0,    (APTR)0},
  153.     {  NM_ITEM, "Toggle chat",        "C",    0,    0,    (APTR)Alt_C},
  154.     {  NM_ITEM, NM_BARLABEL,         0 ,    0,    0,    (APTR)0},
  155.     {  NM_ITEM, "Hang up",            "H",    0,    0,    (APTR)Alt_H},
  156.     {  NM_ITEM, "Toggle duplex",        "E",    0,    0,    (APTR)Alt_E},
  157.     {  NM_ITEM, "Toggle 7 bits/8 bits",    "B",    0,    0,    (APTR)Alt_B},
  158.     {  NM_ITEM, NM_BARLABEL,         0 ,    0,    0,    (APTR)0},
  159.     {  NM_ITEM, "Start upload",        "U",    0,    0,    (APTR)PgUp},
  160.     {  NM_ITEM, "Start download",        "D",    0,    0,    (APTR)PgDn},
  161.     {  NM_ITEM, NM_BARLABEL,         0 ,    0,    0,    (APTR)0},
  162.     {  NM_ITEM, "Exit HydraCom",        "Q",    0,    0,    (APTR)Alt_X},
  163.     { NM_END,   0,                 0 ,    0,    0,    (APTR)0}
  164. };
  165.  
  166.     /* OpenConsole():
  167.      *
  168.      *    Open a console window.
  169.      */
  170.  
  171. STATIC BOOL __inline
  172. OpenConsole(struct Screen *Screen,LONG Top,LONG Height,STRPTR Title,BOOL Resize,struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
  173. {
  174.     struct Window *Window;
  175.  
  176.     if(Window = OpenWindowTags(NULL,
  177.         WA_Left,        0,
  178.         WA_Top,            Top,
  179.         WA_Width,        Screen -> Width,
  180.         WA_Height,        Height,
  181.         WA_Title,        Title,
  182.         WA_SimpleRefresh,    TRUE,
  183.         WA_DepthGadget,        TRUE,
  184.         WA_DragBar,        TRUE,
  185.         WA_SizeGadget,        Resize,
  186.         WA_SizeBRight,        TRUE,
  187.         WA_CustomScreen,    Screen,
  188.         WA_RMBTrap,        TRUE,
  189.         WA_NewLookMenus,    TRUE,
  190.     TAG_DONE))
  191.     {
  192.         struct IOStdReq *ConsoleRequest;
  193.  
  194.         if(Window -> RPort -> Font -> tf_Flags & FPF_PROPORTIONAL)
  195.             SetFont(Window -> RPort,GfxBase -> DefaultFont);
  196.  
  197.         if(ConsoleRequest = (struct IOStdReq *)CreateIORequest(ConsoleWritePort,sizeof(struct IOStdReq)))
  198.         {
  199.             ConsoleRequest -> io_Data = Window;
  200.  
  201.             if(!OpenDevice("console.device",CONU_CHARMAP,ConsoleRequest,CONFLAG_DEFAULT))
  202.             {
  203.                 WindowLimits(Window,Window -> BorderLeft + 10 * Window -> RPort -> Font -> tf_XSize * 10 + Window -> BorderRight,Window -> BorderTop + 2 * Window -> RPort -> Font -> tf_YSize + Window -> BorderBottom,Screen -> Width,Screen -> Height);
  204.  
  205.                     /* Turn off the cursor. */
  206.  
  207.                 ConPrintf(ConsoleRequest,"\033[0 p");
  208.  
  209.                 *WindowPtr    = Window;
  210.                 *ConsolePtr    = ConsoleRequest;
  211.  
  212.                 return(TRUE);
  213.             }
  214.  
  215.             DeleteIORequest(ConsoleRequest);
  216.         }
  217.  
  218.         CloseWindow(Window);
  219.     }
  220.  
  221.     return(FALSE);
  222. }
  223.  
  224.     /* CloseConsole():
  225.      *
  226.      *    Close a console window.
  227.      */
  228.  
  229. STATIC VOID __inline
  230. CloseConsole(struct Window **WindowPtr,struct IOStdReq **ConsolePtr)
  231. {
  232.     if(*ConsolePtr)
  233.     {
  234.         CloseDevice(*ConsolePtr);
  235.  
  236.         DeleteIORequest(*ConsolePtr);
  237.  
  238.         *ConsolePtr = NULL;
  239.     }
  240.  
  241.     if(*WindowPtr)
  242.     {
  243.         CloseWindow(*WindowPtr);
  244.  
  245.         *WindowPtr = NULL;
  246.     }
  247. }
  248.  
  249.     /* CloneSerialBuffer():
  250.      *
  251.      *    Clone a SerialBuffer structure.
  252.      */
  253.  
  254. STATIC struct SerialBuffer * __regargs
  255. CloneSerialBuffer(struct SerialBuffer *Source,struct MsgPort *MsgPort)
  256. {
  257.     struct SerialBuffer *Buffer;
  258.  
  259.     if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Source -> SerialSize,MEMF_ANY | MEMF_PUBLIC))
  260.     {
  261.         Buffer -> SerialBuffer    = Buffer -> SerialIndex = (UBYTE *)(Buffer + 1);
  262.         Buffer -> SerialFilled    = 0;
  263.         Buffer -> SerialTop    = Buffer -> SerialBuffer + Source -> SerialSize;
  264.         Buffer -> SerialSize    = Source -> SerialSize;
  265.         Buffer -> IsClone    = TRUE;
  266.         Buffer -> IsBusy    = FALSE;
  267.  
  268.         if(Buffer -> SerialRequest = (struct IOExtSer *)AllocVec(sizeof(struct IOExtSer),MEMF_ANY | MEMF_PUBLIC))
  269.         {
  270.             CopyMem(Source -> SerialRequest,Buffer -> SerialRequest,sizeof(struct IOExtSer));
  271.  
  272.             Buffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = MsgPort;
  273.  
  274.             return(Buffer);
  275.         }
  276.         else
  277.             cprint("Could not create serial request\n");
  278.  
  279.         FreeVec(Buffer);
  280.     }
  281.     else
  282.         cprint("Could not create serial buffer\n");
  283.  
  284.     return(NULL);
  285. }
  286.  
  287.     /* DeleteSerialBuffer():
  288.      *
  289.      *    Delete a SerialBuffer structure.
  290.      */
  291.  
  292. STATIC VOID __regargs
  293. DeleteSerialBuffer(struct SerialBuffer *Buffer)
  294. {
  295.     if(Buffer)
  296.     {
  297.         if(Buffer -> IsBusy)
  298.         {
  299.             if(!CheckIO(Buffer -> SerialRequest))
  300.                 AbortIO(Buffer -> SerialRequest);
  301.  
  302.             WaitIO(Buffer -> SerialRequest);
  303.         }
  304.  
  305.         if(Buffer -> IsClone)
  306.             FreeVec(Buffer -> SerialRequest);
  307.         else
  308.         {
  309.             CloseDevice(Buffer -> SerialRequest);
  310.  
  311.             DeleteIORequest(Buffer -> SerialRequest);
  312.         }
  313.  
  314.         FreeVec(Buffer);
  315.     }
  316. }
  317.  
  318.     /* CreateSerialBuffer():
  319.      *
  320.      *    Create a serial buffer structure.
  321.      */
  322.  
  323. STATIC struct SerialBuffer * __regargs
  324. CreateSerialBuffer(STRPTR Device,LONG Unit,LONG Size,struct MsgPort *MsgPort)
  325. {
  326.     struct SerialBuffer *Buffer;
  327.  
  328.     if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Size,MEMF_ANY | MEMF_PUBLIC))
  329.     {
  330.         Buffer -> SerialBuffer    = Buffer -> SerialIndex = (UBYTE *)(Buffer + 1);
  331.         Buffer -> SerialFilled    = 0;
  332.         Buffer -> SerialTop    = Buffer -> SerialBuffer + Size;
  333.         Buffer -> SerialSize    = Size;
  334.         Buffer -> IsClone    = FALSE;
  335.         Buffer -> IsBusy    = FALSE;
  336.  
  337.         if(Buffer -> SerialRequest = (struct IOExtSer *)CreateIORequest(MsgPort,sizeof(struct IOExtSer)))
  338.         {
  339.  
  340.         Buffer -> SerialRequest -> io_SerFlags = SERF_SHARED|SERF_XDISABLED|SERF_RAD_BOOGIE;
  341.  
  342.             if(!OpenDevice(Device,Unit,Buffer->SerialRequest,(ULONG)0L))
  343.                 {
  344.                 return(Buffer);
  345.                 } else {
  346.                 cprint("Could not open \"%s\", unit %d\n",Device,Unit);
  347.                 DeleteIORequest(Buffer -> SerialRequest);
  348.                 }
  349.  
  350.         } else {
  351.         cprint("Could not create serial request\n");
  352.         }
  353.  
  354.         FreeVec(Buffer);
  355.     }
  356.     else
  357.         cprint("Could not create serial buffer\n");
  358.  
  359.     return(NULL);
  360. }
  361.  
  362.     /* OpenAll():
  363.      *
  364.      *    Allocate all the resources required.
  365.      */
  366.  
  367. STATIC BOOL
  368. OpenAll(STRPTR Device,LONG Unit)
  369. {
  370.     LONG Top,Lines,BorderSize,FontSize,ExtraLines,RemainingLines,TotalHeight;
  371.     UWORD Pens = (UWORD)~0;
  372.  
  373.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  374.     {
  375.         cprint("Could not open intuition.library v37\n");
  376.  
  377.         return(FALSE);
  378.     }
  379.  
  380.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  381.     {
  382.         cprint("Could not open graphics.library v37\n");
  383.  
  384.         return(FALSE);
  385.     }
  386.  
  387.     if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
  388.     {
  389.         cprint("Could not open gadtools.library v37\n");
  390.  
  391.         return(FALSE);
  392.     }
  393.  
  394.     if(!(UtilityBase = OpenLibrary("utility.library",37)))
  395.     {
  396.         cprint("Could not open utility.library v37\n");
  397.  
  398.         return(FALSE);
  399.     }
  400.  
  401.     if(!(TimePort = CreateMsgPort()))
  402.     {
  403.         cprint("Could not create timer port\n");
  404.  
  405.         return(FALSE);
  406.     }
  407.  
  408.     if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest))))
  409.     {
  410.         cprint("Could not create timer request\n");
  411.  
  412.         return(FALSE);
  413.     }
  414.  
  415.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
  416.     {
  417.         cprint("Could not open timer\n");
  418.  
  419.         return(FALSE);
  420.     }
  421.  
  422.     TimerBase = (struct Library *)TimeRequest -> tr_node . io_Device;
  423.  
  424.     if(!(Anchor = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath) + 512,MEMF_ANY | MEMF_CLEAR)))
  425.     {
  426.         cprint("Could not allocate pattern matching buffe\n");
  427.  
  428.         return(FALSE);
  429.     }
  430.  
  431.     Anchor -> ap_Strlen = 512;
  432.  
  433.     if(!(ReadPort = CreateMsgPort()))
  434.     {
  435.         cprint("Could not create serial read port\n");
  436.  
  437.         return(FALSE);
  438.     }
  439.  
  440.     if(!(WritePort = CreateMsgPort()))
  441.     {
  442.         cprint("Could not create serial write port\n");
  443.  
  444.         return(FALSE);
  445.     }
  446.  
  447.     Forbid();
  448.  
  449.     if(RendezvousSemaphore = (struct RendezvousSemaphore *)FindSemaphore(Device))
  450.     {
  451.         ObtainSemaphore(RendezvousSemaphore);
  452.  
  453.         if(!(RendezvousData = (*RendezvousSemaphore -> rs_Login)(ReadPort,WritePort,NULL)))
  454.         {
  455.             Permit();
  456.  
  457.             ReleaseSemaphore(RendezvousSemaphore);
  458.  
  459.             RendezvousSemaphore = NULL;
  460.  
  461.             cprint("Could not link to `term'\n");
  462.  
  463.             return(FALSE);
  464.         }
  465.     }
  466.  
  467.     Permit();
  468.  
  469.     if(!(ConsoleReadPort = CreateMsgPort()))
  470.     {
  471.         cprint("Could not create console read port\n");
  472.  
  473.         return(FALSE);
  474.     }
  475.  
  476.     if(!(ConsoleWritePort = CreateMsgPort()))
  477.     {
  478.         cprint("Could not create console write port\n");
  479.  
  480.         return(FALSE);
  481.     }
  482.  
  483.     if(!(ConsoleReadRequest = (struct IOStdReq *)AllocVec(sizeof(struct IOStdReq),MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR)))
  484.     {
  485.         cprint("Could not create console read request\n");
  486.  
  487.         return(FALSE);
  488.     }
  489.  
  490.     if(!RendezvousData)
  491.     {
  492.         if(!(ReadBuffer = CreateSerialBuffer(Device,Unit,BUFFER_SIZE,ReadPort)))
  493.             return(FALSE);
  494.     }
  495.     else
  496.     {
  497.         if(ReadBuffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + BUFFER_SIZE,MEMF_ANY | MEMF_PUBLIC))
  498.         {
  499.             ReadBuffer -> SerialBuffer    = ReadBuffer -> SerialIndex = (UBYTE *)(ReadBuffer + 1);
  500.             ReadBuffer -> SerialFilled    = 0;
  501.             ReadBuffer -> SerialTop        = ReadBuffer -> SerialBuffer + BUFFER_SIZE;
  502.             ReadBuffer -> SerialSize    = BUFFER_SIZE;
  503.             ReadBuffer -> IsClone        = TRUE;
  504.             ReadBuffer -> IsBusy        = FALSE;
  505.             ReadBuffer -> SerialRequest    = &RendezvousData -> rd_ReadRequest;
  506.         }
  507.         else
  508.         {
  509.             cprint("Could not create serial ReadBuffer\n");
  510.  
  511.             return(FALSE);
  512.         }
  513.     }
  514.  
  515.     if(!(ThisBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
  516.         return(FALSE);
  517.  
  518.     if(!(NextBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
  519.         return(FALSE);
  520.  
  521.     if(!(PublicScreen = LockPubScreen(NULL)))
  522.     {
  523.         cprint("Could not find default public screen\n");
  524.  
  525.         return(FALSE);
  526.     }
  527.  
  528.     if(RendezvousData)
  529.     {
  530.         if(!(Screen = RendezvousData -> rd_Screen))
  531.             Screen = PublicScreen;
  532.     }
  533.     else
  534.     {
  535.         if(!(Screen = OpenScreenTags(NULL,
  536.             SA_DisplayID,    GetVPModeID(&PublicScreen -> ViewPort),
  537.             SA_Overscan,    OSCAN_TEXT,
  538.             SA_Depth,    2,
  539.             SA_Title,    PRGNAME " " VERSION " " HC_OS " Amiga rev 2, ported by Olaf `Olsen' Barthel",
  540.             SA_Behind,    TRUE,
  541.             SA_SysFont,    1,
  542.             SA_Pens,    &Pens,
  543.         TAG_DONE)))
  544.         {
  545.             cprint("Could not open screen\n");
  546.  
  547.             return(FALSE);
  548.         }
  549.     }
  550.  
  551.     if(!(VisualInfo = GetVisualInfo(Screen,TAG_DONE)))
  552.     {
  553.         cprint("Could not obtain screen visual info\n");
  554.  
  555.         return(FALSE);
  556.     }
  557.  
  558.     if(!(Menu = CreateMenus(MenuTemplate,TAG_DONE)))
  559.     {
  560.         cprint("Could not create menus\n");
  561.  
  562.         return(FALSE);
  563.     }
  564.  
  565.     if(!LayoutMenus(Menu,VisualInfo,
  566.         GTMN_TextAttr,        Screen -> Font,
  567.         GTMN_NewLookMenus,    TRUE,
  568.     TAG_DONE))
  569.     {
  570.         cprint("Could not layout menus\n");
  571.  
  572.         return(FALSE);
  573.     }
  574.  
  575.     Top        = Screen -> BarHeight + 1;
  576.     BorderSize    = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + Screen -> WBorBottom;
  577.     FontSize    = GfxBase -> DefaultFont -> tf_YSize;
  578.     TotalHeight    = Screen -> Height - Top;
  579.     Lines        = (TotalHeight - 3 - 4 * BorderSize) / FontSize;
  580.     ExtraLines    = Lines > 23 ? (Lines - 23) / 3 : 0;
  581.     RemainingLines    = Lines > 23 + ExtraLines * 3 ? Lines - (23 + ExtraLines * 3) : 0;
  582.  
  583.     if(!OpenConsole(Screen,Top,BorderSize + (6 + ExtraLines) * FontSize,"Log",TRUE,&LogWindow,&LogRequest))
  584.     {
  585.         cprint("Could not open console window #1\n");
  586.  
  587.         return(FALSE);
  588.     }
  589.  
  590.     TotalHeight    -= LogWindow -> Height + 1;
  591.     Top        += LogWindow -> Height + 1;
  592.  
  593.     if(!OpenConsole(Screen,Top,BorderSize + 3 * FontSize,"File",FALSE,&FileWindow,&FileRequest))
  594.     {
  595.         cprint("Could not open console window #2\n");
  596.  
  597.         return(FALSE);
  598.     }
  599.  
  600.     TotalHeight    -= FileWindow -> Height + 1;
  601.     Top        += FileWindow -> Height + 1;
  602.  
  603.     if(!OpenConsole(Screen,Top,BorderSize + (8 + RemainingLines) * FontSize,"Remote",TRUE,&RemoteWindow,&RemoteRequest))
  604.     {
  605.         cprint("Could not open console window #3\n");
  606.  
  607.         return(FALSE);
  608.     }
  609.  
  610.     TotalHeight    -= RemoteWindow -> Height + 1;
  611.     Top        += RemoteWindow -> Height + 1;
  612.  
  613.     if(!OpenConsole(Screen,Top,TotalHeight,"Local (Press Amiga+X to start/end chat mode)",TRUE,&LocalWindow,&LocalRequest))
  614.     {
  615.         cprint("Could not open console window #4\n");
  616.  
  617.         return(FALSE);
  618.     }
  619.  
  620.     SetMenuStrip(LocalWindow,Menu);
  621.  
  622.     if(!ModifyIDCMP(LocalWindow,IDCMP_MENUPICK))
  623.     {
  624.         cprint("Could not modify IDCMP flags\n");
  625.  
  626.         return(FALSE);
  627.     }
  628.  
  629.     LocalWindow -> Flags &= ~WFLG_RMBTRAP;
  630.  
  631.     CopyMem(LocalRequest,ConsoleReadRequest,sizeof(struct IOStdReq));
  632.  
  633.     ConsoleReadRequest -> io_Message . mn_ReplyPort = ConsoleReadPort;
  634.  
  635.         /* Turn the cursors back on. */
  636.  
  637.     ConPrintf(LocalRequest,"\33[ p");
  638.     ConPrintf(RemoteRequest,"\33[ p");
  639.  
  640.     ConsoleReadRequest -> io_Command    = CMD_READ;
  641.     ConsoleReadRequest -> io_Data        = &ConsoleChar;
  642.     ConsoleReadRequest -> io_Length        = 1;
  643.  
  644.     ClrSignal(SIG_CONREAD);
  645.     SendIO(ConsoleReadRequest);
  646.  
  647.     ThisProcess = (struct Process *)FindTask(NULL);
  648.  
  649.     OldPtr = ThisProcess -> pr_WindowPtr;
  650.  
  651.     ThisProcess -> pr_WindowPtr = (APTR)LocalWindow;
  652.  
  653.     ScreenToFront(Screen);
  654.  
  655.     ActivateWindow(LocalWindow);
  656.  
  657.     UnlockPubScreen(NULL,PublicScreen);
  658.  
  659.     PublicScreen = NULL;
  660.  
  661.     return(TRUE);
  662. }
  663.  
  664.     /* CloseAll():
  665.      *
  666.      *    Close all the resources.
  667.      */
  668.  
  669. STATIC VOID
  670. CloseAll(VOID)
  671. {
  672.     if(LocalWindow)
  673.         ClearMenuStrip(LocalWindow);
  674.  
  675.     if(Menu)
  676.         FreeMenus(Menu);
  677.  
  678.     if(VisualInfo)
  679.         FreeVisualInfo(VisualInfo);
  680.  
  681.     if(AnchorUsed)
  682.         MatchEnd(Anchor);
  683.  
  684.     if(Anchor)
  685.         FreeVec(Anchor);
  686.  
  687.     if(ThisProcess)
  688.         ThisProcess -> pr_WindowPtr = OldPtr;
  689.  
  690.     if(ConsoleReadRequest)
  691.     {
  692.         if(ConsoleReadRequest -> io_Device)
  693.         {
  694.             if(!CheckIO(ConsoleReadRequest))
  695.                 AbortIO(ConsoleReadRequest);
  696.  
  697.             WaitIO(ConsoleReadRequest);
  698.         }
  699.  
  700.         FreeVec(ConsoleReadRequest);
  701.     }
  702.  
  703.     CloseConsole(&LocalWindow,&LocalRequest);
  704.     CloseConsole(&RemoteWindow,&RemoteRequest);
  705.     CloseConsole(&FileWindow,&FileRequest);
  706.     CloseConsole(&LogWindow,&LogRequest);
  707.  
  708.     if(!RendezvousData && Screen)
  709.         CloseScreen(Screen);
  710.  
  711.     if(PublicScreen)
  712.         UnlockPubScreen(NULL,PublicScreen);
  713.  
  714.     DeleteSerialBuffer(NextBuffer);
  715.     DeleteSerialBuffer(ThisBuffer);
  716.  
  717.     if(RendezvousData)
  718.     {
  719.         if(ReadBuffer -> IsBusy)
  720.         {
  721.             if(!CheckIO(ReadBuffer -> SerialRequest))
  722.                 AbortIO(ReadBuffer -> SerialRequest);
  723.  
  724.             WaitIO(ReadBuffer -> SerialRequest);
  725.         }
  726.  
  727.         FreeVec(ReadBuffer);
  728.     }
  729.     else
  730.         DeleteSerialBuffer(ReadBuffer);
  731.  
  732.     if(ConsoleWritePort)
  733.         DeleteMsgPort(ConsoleWritePort);
  734.  
  735.     if(ConsoleReadPort)
  736.         DeleteMsgPort(ConsoleReadPort);
  737.  
  738.     if(WritePort)
  739.         DeleteMsgPort(WritePort);
  740.  
  741.     if(ReadPort)
  742.         DeleteMsgPort(ReadPort);
  743.  
  744.     if(TimeRequest)
  745.     {
  746.         if(TimeRequest -> tr_node . io_Device)
  747.             CloseDevice(TimeRequest);
  748.  
  749.         DeleteIORequest(TimeRequest);
  750.     }
  751.  
  752.     if(TimePort)
  753.         DeleteMsgPort(TimePort);
  754.  
  755.     if(UtilityBase)
  756.         CloseLibrary(UtilityBase);
  757.  
  758.     if(GadToolsBase)
  759.         CloseLibrary(GadToolsBase);
  760.  
  761.     if(GfxBase)
  762.         CloseLibrary(GfxBase);
  763.  
  764.     if(IntuitionBase)
  765.         CloseLibrary(IntuitionBase);
  766.  
  767.     if(RendezvousData)
  768.     {
  769.         (*RendezvousSemaphore -> rs_Logoff)(RendezvousData);
  770.  
  771.         RendezvousData = NULL;
  772.     }
  773.  
  774.     if(RendezvousSemaphore)
  775.     {
  776.         ReleaseSemaphore(RendezvousSemaphore);
  777.  
  778.         RendezvousSemaphore = NULL;
  779.     }
  780. }
  781.  
  782.     /* ConPutc():
  783.      *
  784.      *    Output a single character.
  785.      */
  786.  
  787. VOID __stdargs
  788. ConPutc(struct IOStdReq *Request,UBYTE Char)
  789. {
  790.     Request -> io_Command    = CMD_WRITE;
  791.     Request -> io_Data    = &Char;
  792.     Request -> io_Length    = 1;
  793.  
  794.     DoIO(Request);
  795. }
  796.  
  797.     /* ConPuts():
  798.      *
  799.      *    Output a string.
  800.      */
  801.  
  802. VOID
  803. ConPuts(struct IOStdReq *Request,STRPTR String)
  804. {
  805.     Request -> io_Command    = CMD_WRITE;
  806.     Request -> io_Data    = String;
  807.     Request -> io_Length    = strlen(String);
  808.  
  809.     DoIO(Request);
  810. }
  811.  
  812.     /* ConPrintf():
  813.      *
  814.      *    Formatted console output.
  815.      */
  816.  
  817. VOID __stdargs
  818. ConPrintf(struct IOStdReq *Request,STRPTR Format,...)
  819. {
  820.     STATIC UBYTE Buffer[512];
  821.  
  822.     va_list VarArgs;
  823.  
  824.     va_start(VarArgs,Format);
  825.     vsprintf(Buffer,Format,VarArgs);
  826.     va_end(VarArgs);
  827.  
  828.     Request -> io_Command    = CMD_WRITE;
  829.     Request -> io_Data    = Buffer;
  830.     Request -> io_Length    = strlen(Buffer);
  831.  
  832.     DoIO(Request);
  833. }
  834.  
  835.     /* ConMove():
  836.      *
  837.      *    Move the cursor to a new position.
  838.      */
  839.  
  840. VOID
  841. ConMove(struct IOStdReq *Request,LONG x,LONG y)
  842. {
  843.     ConPrintf(Request,"\33[%ld;%ldH",y,x);
  844. }
  845.  
  846.     /* ConClear():
  847.      *
  848.      *    Clear the console window.
  849.      */
  850.  
  851. VOID
  852. ConClear(struct IOStdReq *Request)
  853. {
  854.     struct ConUnit *ConUnit = (struct ConUnit *)Request -> io_Device;
  855.     LONG x,y;
  856.  
  857.     x = ConUnit -> cu_XCCP;
  858.     y = ConUnit -> cu_YCCP;
  859.  
  860.     ConPrintf(Request,"\f\33[%ld;%ldH",y,x);
  861. }
  862.  
  863.     /* ConGetKey():
  864.      *
  865.      *    Read a character from a console window.
  866.      */
  867.  
  868. int
  869. ConGetKey()
  870. {
  871.     if(ConsoleReady)
  872.     {
  873.         int Result = ConsoleChar;
  874.  
  875.         ConsoleReady = FALSE;
  876.  
  877.         ConsoleReadRequest -> io_Command    = CMD_READ;
  878.         ConsoleReadRequest -> io_Data        = &ConsoleChar;
  879.         ConsoleReadRequest -> io_Length        = 1;
  880.  
  881.         ClrSignal(SIG_CONREAD);
  882.         SendIO(ConsoleReadRequest);
  883.  
  884.         return(Result);
  885.     }
  886.     else
  887.     {
  888.         int Result = 0;
  889.  
  890.         if(WindowReady)
  891.         {
  892.             struct IntuiMessage *IntuiMessage;
  893.             ULONG MsgClass;
  894.             UWORD MsgCode;
  895.  
  896.             while(IntuiMessage = (struct IntuiMessage *)GetMsg(LocalWindow -> UserPort))
  897.             {
  898.                 MsgClass    = IntuiMessage -> Class;
  899.                 MsgCode        = IntuiMessage -> Code;
  900.  
  901.                 ReplyMsg(IntuiMessage);
  902.  
  903.                 if(MsgClass == IDCMP_MENUPICK)
  904.                 {
  905.                     struct MenuItem *Item;
  906.  
  907.                     while(MsgCode != MENUNULL)
  908.                     {
  909.                         if(Item = ItemAddress(Menu,MsgCode))
  910.                         {
  911.                             if(MENU_USERDATA(Item))
  912.                             {
  913.                                 if(!Result)
  914.                                     Result = (int)MENU_USERDATA(Item);
  915.                             }
  916.  
  917.                             MsgCode = Item -> NextSelect;
  918.                         }
  919.                         else
  920.                             break;
  921.                     }
  922.                 }
  923.             }
  924.  
  925.             WindowReady = FALSE;
  926.         }
  927.  
  928.         return(Result);
  929.     }
  930. }
  931.  
  932.     /* ConScanKey():
  933.      *
  934.      *    Check for a keyboard event.
  935.      */
  936.  
  937. int
  938. ConScanKey()
  939. {
  940.     if(ConsoleReady || WindowReady)
  941.         return(1);
  942.     else
  943.     {
  944.         int Result = 0;
  945.  
  946.         if(CheckSignal(SIG_WINDOW))
  947.         {
  948.             WindowReady = TRUE;
  949.  
  950.             Result = 1;
  951.         }
  952.  
  953.         if(CheckIO(ConsoleReadRequest))
  954.         {
  955.             if(!WaitIO(ConsoleReadRequest))
  956.             {
  957.                 ConsoleReady = TRUE;
  958.  
  959.                 return(1);
  960.             }
  961.             else
  962.             {
  963.                 ConsoleReadRequest -> io_Command    = CMD_READ;
  964.                 ConsoleReadRequest -> io_Data        = &ConsoleChar;
  965.                 ConsoleReadRequest -> io_Length        = 1;
  966.  
  967.                 ClrSignal(SIG_CONREAD);
  968.                 SendIO(ConsoleReadRequest);
  969.             }
  970.         }
  971.  
  972.         return(Result);
  973.     }
  974.  
  975.     return(0);
  976. }
  977.  
  978.     /* dtr_out(byte flag):
  979.      *
  980.      *    If flag == 0 -> drop DTR signal, else set it.
  981.      */
  982.  
  983. VOID
  984. dtr_out(byte flag)
  985. {
  986.     if(!flag && !RendezvousData)
  987.     {
  988.         if(ThisBuffer -> IsBusy)
  989.         {
  990.             WaitIO(ThisBuffer -> SerialRequest);
  991.  
  992.             ThisBuffer -> IsBusy        = FALSE;
  993.             ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  994.         }
  995.  
  996.         if(ReadBuffer -> IsBusy)
  997.         {
  998.             if(!CheckIO(ReadBuffer -> SerialRequest))
  999.                 AbortIO(ReadBuffer -> SerialRequest);
  1000.  
  1001.             WaitIO(ReadBuffer -> SerialRequest);
  1002.  
  1003.             ReadBuffer -> IsBusy        = FALSE;
  1004.             ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1005.             ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1006.  
  1007.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1008.  
  1009.             DoIO(ReadBuffer -> SerialRequest);
  1010.  
  1011.             if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1012.             {
  1013.                 LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  1014.  
  1015.                 if(Size > 0)
  1016.                 {
  1017.                     if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1018.                         Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1019.  
  1020.                     ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1021.                     ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  1022.                     ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  1023.  
  1024.                     DoIO(ReadBuffer -> SerialRequest);
  1025.  
  1026.                     ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1027.                 }
  1028.             }
  1029.         }
  1030.  
  1031.         CloseDevice(ReadBuffer -> SerialRequest);
  1032.  
  1033.         TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1034.         TimeRequest -> tr_time . tv_secs    = 1;
  1035.         TimeRequest -> tr_time . tv_micro    = 0;
  1036.  
  1037.         DoIO(TimeRequest);
  1038.  
  1039.         if(OpenDevice(device,port,ReadBuffer -> SerialRequest,NULL))
  1040.         {
  1041.             CloseAll();
  1042.  
  1043.             exit(10);
  1044.         }
  1045.         else
  1046.         {
  1047.             ReadBuffer -> SerialRequest -> io_Baud        = ThisBuffer -> SerialRequest -> io_Baud;
  1048.             ReadBuffer -> SerialRequest -> io_ReadLen    = ThisBuffer -> SerialRequest -> io_ReadLen;
  1049.             ReadBuffer -> SerialRequest -> io_WriteLen    = ThisBuffer -> SerialRequest -> io_WriteLen;
  1050.             ReadBuffer -> SerialRequest -> io_SerFlags    = ThisBuffer -> SerialRequest -> io_SerFlags;
  1051.  
  1052.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1053.  
  1054.             DoIO(ReadBuffer -> SerialRequest);
  1055.  
  1056.             CopyMem(ReadBuffer -> SerialRequest,ThisBuffer -> SerialRequest,sizeof(struct IOExtSer));
  1057.  
  1058.             ThisBuffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  1059.  
  1060.             CopyMem(ReadBuffer -> SerialRequest,NextBuffer -> SerialRequest,sizeof(struct IOExtSer));
  1061.  
  1062.             NextBuffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  1063.         }
  1064.     }
  1065. }
  1066.  
  1067.     /* com_flow(byte flags):
  1068.      *
  1069.      *    The bit mask `flags' determines the style(s) of
  1070.      *    handshaking:
  1071.      *
  1072.      *    if (flags & 9) -> enable xON/xOFF software handshaking,
  1073.      *    if (flags & 2) -> enable RTS/CTS hardware handshaking
  1074.      */
  1075.  
  1076. VOID
  1077. com_flow(byte flags)
  1078. {
  1079.     if(ThisBuffer -> IsBusy)
  1080.     {
  1081.         WaitIO(ThisBuffer -> SerialRequest);
  1082.  
  1083.         ThisBuffer -> IsBusy        = FALSE;
  1084.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1085.     }
  1086.  
  1087.     if(ReadBuffer -> IsBusy)
  1088.     {
  1089.         if(!CheckIO(ReadBuffer -> SerialRequest))
  1090.             AbortIO(ReadBuffer -> SerialRequest);
  1091.  
  1092.         WaitIO(ReadBuffer -> SerialRequest);
  1093.  
  1094.         ReadBuffer -> IsBusy        = FALSE;
  1095.         ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1096.         ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1097.  
  1098.         ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1099.  
  1100.         DoIO(ReadBuffer -> SerialRequest);
  1101.  
  1102.         if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1103.         {
  1104.             LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  1105.  
  1106.             if(Size > 0)
  1107.             {
  1108.                 if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1109.                     Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1110.  
  1111.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1112.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  1113.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  1114.  
  1115.                 DoIO(ReadBuffer -> SerialRequest);
  1116.  
  1117.                 ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1118.             }
  1119.         }
  1120.     }
  1121.  
  1122.     if(flags & 2)
  1123.         ReadBuffer -> SerialRequest -> io_SerFlags |= SERF_7WIRE;
  1124.     else
  1125.         ReadBuffer -> SerialRequest -> io_SerFlags &= ~SERF_7WIRE;
  1126.  
  1127.     if(flags & 9)
  1128.         ReadBuffer -> SerialRequest -> io_SerFlags &= ~SERF_XDISABLED;
  1129.     else
  1130.         ReadBuffer -> SerialRequest -> io_SerFlags |= SERF_XDISABLED;
  1131.         ReadBuffer -> SerialRequest -> io_SerFlags = SERF_SHARED;
  1132.  
  1133.     DoIO(ReadBuffer -> SerialRequest);
  1134.  
  1135.     ThisBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
  1136.     NextBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
  1137. }
  1138.  
  1139.     /* com_setspeed(word speed):
  1140.      *
  1141.      *    Set the transfer speed (in bits/second).
  1142.      */
  1143.  
  1144. VOID
  1145. com_setspeed(word speed)
  1146. {
  1147.     if(ThisBuffer -> IsBusy)
  1148.     {
  1149.         WaitIO(ThisBuffer -> SerialRequest);
  1150.  
  1151.         ThisBuffer -> IsBusy        = FALSE;
  1152.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1153.     }
  1154.  
  1155.     if(ReadBuffer -> IsBusy)
  1156.     {
  1157.         if(!CheckIO(ReadBuffer -> SerialRequest))
  1158.             AbortIO(ReadBuffer -> SerialRequest);
  1159.  
  1160.         WaitIO(ReadBuffer -> SerialRequest);
  1161.  
  1162.         ReadBuffer -> IsBusy        = FALSE;
  1163.         ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1164.         ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1165.  
  1166.         ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1167.  
  1168.         DoIO(ReadBuffer -> SerialRequest);
  1169.  
  1170.         if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1171.         {
  1172.             LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  1173.  
  1174.             if(Size > 0)
  1175.             {
  1176.                 if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1177.                     Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1178.  
  1179.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1180.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  1181.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  1182.  
  1183.                 DoIO(ReadBuffer -> SerialRequest);
  1184.  
  1185.                 ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1186.             }
  1187.         }
  1188.     }
  1189.  
  1190.     ReadBuffer -> SerialRequest -> io_Baud = speed;
  1191.  
  1192.     if(parity)
  1193.     {
  1194.         ReadBuffer -> SerialRequest -> io_ReadLen = ReadBuffer -> SerialRequest -> io_WriteLen = 7;
  1195.         ReadBuffer -> SerialRequest -> io_SerFlags |= SERF_PARTY_ON;
  1196.     }
  1197.     else
  1198.     {
  1199.         ReadBuffer -> SerialRequest -> io_ReadLen = ReadBuffer -> SerialRequest -> io_WriteLen = 8;
  1200.         ReadBuffer -> SerialRequest -> io_SerFlags &= ~SERF_PARTY_ON;
  1201.     }
  1202.  
  1203.     ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1204.  
  1205.     DoIO(ReadBuffer -> SerialRequest);
  1206.  
  1207.     ThisBuffer -> SerialRequest -> io_Baud        = ReadBuffer -> SerialRequest -> io_Baud;
  1208.     ThisBuffer -> SerialRequest -> io_ReadLen    = ReadBuffer -> SerialRequest -> io_ReadLen;
  1209.     ThisBuffer -> SerialRequest -> io_WriteLen    = ReadBuffer -> SerialRequest -> io_WriteLen;
  1210.     ThisBuffer -> SerialRequest -> io_SerFlags    = ReadBuffer -> SerialRequest -> io_SerFlags;
  1211.  
  1212.     NextBuffer -> SerialRequest -> io_Baud        = ReadBuffer -> SerialRequest -> io_Baud;
  1213.     NextBuffer -> SerialRequest -> io_ReadLen    = ReadBuffer -> SerialRequest -> io_ReadLen;
  1214.     NextBuffer -> SerialRequest -> io_WriteLen    = ReadBuffer -> SerialRequest -> io_WriteLen;
  1215.     NextBuffer -> SerialRequest -> io_SerFlags    = ReadBuffer -> SerialRequest -> io_SerFlags;
  1216. }
  1217.  
  1218.     /* com_putblock(byte *s,word len):
  1219.      *
  1220.      *    Send a data block asynchronously.
  1221.      */
  1222.  
  1223. VOID
  1224. com_putblock(byte *s,word len)
  1225. {
  1226.     struct SerialBuffer *Swap = ThisBuffer;
  1227.  
  1228.     if(ThisBuffer -> IsBusy)
  1229.         WaitIO(ThisBuffer -> SerialRequest);
  1230.     else
  1231.     {
  1232.         if(ThisBuffer -> SerialIndex > ThisBuffer -> SerialBuffer)
  1233.         {
  1234.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1235.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  1236.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  1237.  
  1238.             DoIO(ThisBuffer -> SerialRequest);
  1239.         }
  1240.     }
  1241.  
  1242.     ThisBuffer -> IsBusy        = FALSE;
  1243.     ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1244.  
  1245.     ThisBuffer = NextBuffer;
  1246.     NextBuffer = Swap;
  1247.  
  1248.     if(ThisBuffer -> SerialIndex > ThisBuffer -> SerialBuffer)
  1249.     {
  1250.         ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1251.         ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  1252.         ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  1253.  
  1254.         DoIO(ThisBuffer -> SerialRequest);
  1255.     }
  1256.  
  1257.     ThisBuffer -> IsBusy        = FALSE;
  1258.     ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1259.  
  1260.     while(len > 2 * ThisBuffer -> SerialSize)
  1261.     {
  1262.         ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1263.         ThisBuffer -> SerialRequest -> IOSer . io_Data        = s;
  1264.         ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialSize;
  1265.  
  1266.         s    += ThisBuffer -> SerialSize;
  1267.         len    -= ThisBuffer -> SerialSize;
  1268.  
  1269.         DoIO(ThisBuffer -> SerialRequest);
  1270.     }
  1271.  
  1272.     CopyMem(s,ThisBuffer -> SerialBuffer,MIN(len,ThisBuffer -> SerialSize));
  1273.  
  1274.     ThisBuffer -> IsBusy                    = TRUE;
  1275.     ThisBuffer -> SerialIndex                = ThisBuffer -> SerialBuffer + MIN(len,ThisBuffer -> SerialSize);
  1276.     ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1277.     ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  1278.     ThisBuffer -> SerialRequest -> IOSer . io_Length    = MIN(len,ThisBuffer -> SerialSize);
  1279.  
  1280.     len    -= ThisBuffer -> SerialRequest -> IOSer . io_Length;
  1281.     s    += ThisBuffer -> SerialRequest -> IOSer . io_Length;
  1282.  
  1283.     ClrSignal(SIG_SERWRITE);
  1284.     SendIO(ThisBuffer -> SerialRequest);
  1285.  
  1286.     if(len > 0)
  1287.     {
  1288.         CopyMem(s,NextBuffer -> SerialBuffer,len);
  1289.  
  1290.         NextBuffer -> SerialIndex = NextBuffer -> SerialBuffer + len;
  1291.     }
  1292. }
  1293.  
  1294.     /* breakfunc():
  1295.      *
  1296.      *    Cleanup routine for SAS/C.
  1297.      */
  1298.  
  1299. static int
  1300. breakfunc(void)
  1301. {
  1302.     CloseAll();
  1303.  
  1304.     return(1);
  1305. }
  1306.  
  1307.     /* sys_init(VOID):
  1308.      *
  1309.      *    Initialize this driver implementation.
  1310.      */
  1311.  
  1312. VOID
  1313. sys_init(VOID)
  1314. {
  1315.     if(!OpenAll(device,port))
  1316.     {
  1317.         CloseAll();
  1318.  
  1319.         endprog(2);
  1320.     }
  1321.  
  1322.     onbreak(breakfunc);
  1323. }
  1324.  
  1325.     /* sys_reset(VOID):
  1326.      *
  1327.      *    Perform cleanup for this driver implementation.
  1328.      */
  1329.  
  1330. VOID
  1331. sys_reset(VOID)
  1332. {
  1333.     CloseAll();
  1334. }
  1335.  
  1336.     /* sys_idle(VOID):
  1337.      *
  1338.      *    This routine gets called when the system is idle.
  1339.      *    That's a nice one. We are supposed to call the
  1340.      *    system scheduler, etc.
  1341.      */
  1342.  
  1343. VOID
  1344. sys_idle(VOID)
  1345. {
  1346.     ULONG Signals;
  1347.  
  1348.     if(ReadBuffer -> SerialFilled <= 0 && !ReadBuffer -> IsBusy)
  1349.     {
  1350.         ReadBuffer -> IsBusy                    = TRUE;
  1351.         ReadBuffer -> SerialIndex                = ReadBuffer -> SerialBuffer;
  1352.         ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1353.         ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer;
  1354.         ReadBuffer -> SerialRequest -> IOSer . io_Length    = 1;
  1355.  
  1356.         ClrSignal(SIG_SERREAD);
  1357.         SendIO(ReadBuffer -> SerialRequest);
  1358.     }
  1359.  
  1360.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1361.     TimeRequest -> tr_time . tv_secs    = 1;
  1362.     TimeRequest -> tr_time . tv_micro    = 0;
  1363.  
  1364.     ClrSignal(SIG_TIMER);
  1365.     SendIO(TimeRequest);
  1366.  
  1367.     Signals = Wait(SIG_SERREAD | SIG_SERWRITE | SIG_CONREAD | SIG_WINDOW | SIG_TIMER);
  1368.  
  1369.     if(!(Signals & SIG_TIMER))
  1370.     {
  1371.         if(!CheckIO(TimeRequest))
  1372.             AbortIO(TimeRequest);
  1373.     }
  1374.  
  1375.     WaitIO(TimeRequest);
  1376.  
  1377.     if(Signals & SIG_SERREAD)
  1378.     {
  1379.         WaitIO(ReadBuffer -> SerialRequest);
  1380.  
  1381.         ReadBuffer -> IsBusy        = FALSE;
  1382.         ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1383.         ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1384.  
  1385.         ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1386.  
  1387.         DoIO(ReadBuffer -> SerialRequest);
  1388.  
  1389.         if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1390.         {
  1391.             LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  1392.  
  1393.             if(Size > 0)
  1394.             {
  1395.                 if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1396.                     Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1397.  
  1398.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1399.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  1400.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  1401.  
  1402.                 DoIO(ReadBuffer -> SerialRequest);
  1403.  
  1404.                 ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1405.             }
  1406.         }
  1407.     }
  1408.  
  1409.     if(Signals & SIG_SERWRITE)
  1410.     {
  1411.         struct SerialBuffer *Swap = ThisBuffer;
  1412.  
  1413.         WaitIO(ThisBuffer -> SerialRequest);
  1414.  
  1415.         ThisBuffer -> IsBusy        = FALSE;
  1416.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1417.  
  1418.         ThisBuffer = NextBuffer;
  1419.         NextBuffer = Swap;
  1420.     }
  1421.  
  1422.     if(Signals & SIG_CONREAD)
  1423.     {
  1424.         WaitIO(ConsoleReadRequest);
  1425.  
  1426.         ConsoleReady = TRUE;
  1427.     }
  1428.  
  1429.     if(Signals & SIG_WINDOW)
  1430.         WindowReady = TRUE;
  1431. }
  1432.  
  1433.     /* com_outfull(VOID):
  1434.      *
  1435.      *    Return number of bytes still to be transferred.
  1436.      */
  1437.  
  1438. int
  1439. com_outfull(VOID)
  1440. {
  1441.     return(ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer + NextBuffer -> SerialIndex - NextBuffer -> SerialBuffer);
  1442. }
  1443.  
  1444.     /* carrier(VOID):
  1445.      *
  1446.      *    Return current carrier status.
  1447.      */
  1448.  
  1449. int
  1450. carrier(VOID)
  1451. {
  1452.     if(nocarrier)
  1453.         return(1);
  1454.     else
  1455.     {
  1456.         if(!ThisBuffer -> IsBusy)
  1457.         {
  1458.             ThisBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1459.  
  1460.             DoIO(ThisBuffer -> SerialRequest);
  1461.  
  1462.             if(ThisBuffer -> SerialRequest -> io_Status & CIAF_COMCD)
  1463.                 return(0);
  1464.             else
  1465.                 return(1);
  1466.         }
  1467.         else
  1468.         {
  1469.             NextBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1470.  
  1471.             DoIO(NextBuffer -> SerialRequest);
  1472.  
  1473.             if(NextBuffer -> SerialRequest -> io_Status & CIAF_COMCD)
  1474.                 return(0);
  1475.             else
  1476.                 return(1);
  1477.         }
  1478.     }
  1479. }
  1480.  
  1481.     /* com_flush(VOID):
  1482.      *
  1483.      *    Make sure all pending data gets written.
  1484.      */
  1485.  
  1486. VOID
  1487. com_flush(VOID)
  1488. {
  1489.     if(ThisBuffer -> IsBusy)
  1490.     {
  1491.         WaitIO(ThisBuffer -> SerialRequest);
  1492.  
  1493.         ThisBuffer -> IsBusy        = FALSE;
  1494.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1495.     }
  1496.  
  1497.     if(NextBuffer -> SerialIndex > NextBuffer -> SerialBuffer)
  1498.     {
  1499.         NextBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1500.         NextBuffer -> SerialRequest -> IOSer . io_Data        = NextBuffer -> SerialBuffer;
  1501.         NextBuffer -> SerialRequest -> IOSer . io_Length    = NextBuffer -> SerialIndex - NextBuffer -> SerialBuffer;
  1502.  
  1503.         DoIO(NextBuffer -> SerialRequest);
  1504.  
  1505.         NextBuffer -> SerialIndex = NextBuffer -> SerialBuffer;
  1506.     }
  1507. }
  1508.  
  1509.     /* com_putbyte(byte c):
  1510.      *
  1511.      *    Transmit a single byte, queueing it if necessary.
  1512.      */
  1513.  
  1514. VOID
  1515. com_putbyte(byte c)
  1516. {
  1517.     if(ThisBuffer -> IsBusy)
  1518.     {
  1519.         if(NextBuffer -> SerialIndex + 1 >= NextBuffer -> SerialTop)
  1520.         {
  1521.             struct SerialBuffer *Swap = ThisBuffer;
  1522.  
  1523.             WaitIO(ThisBuffer -> SerialRequest);
  1524.  
  1525.             ThisBuffer -> IsBusy        = FALSE;
  1526.             ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1527.  
  1528.             ThisBuffer = NextBuffer;
  1529.             NextBuffer = Swap;
  1530.  
  1531.             ThisBuffer -> IsBusy                    = TRUE;
  1532.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1533.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  1534.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  1535.  
  1536.             ClrSignal(SIG_SERWRITE);
  1537.             SendIO(ThisBuffer -> SerialRequest);
  1538.         }
  1539.  
  1540.         *NextBuffer -> SerialIndex++ = c;
  1541.     }
  1542.     else
  1543.     {
  1544.         if(ThisBuffer -> SerialIndex + 1 < ThisBuffer -> SerialTop)
  1545.         {
  1546.             *ThisBuffer -> SerialIndex++ = c;
  1547.  
  1548.             ThisBuffer -> IsBusy                    = TRUE;
  1549.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1550.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  1551.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = 1;
  1552.  
  1553.             ClrSignal(SIG_SERWRITE);
  1554.             SendIO(ThisBuffer -> SerialRequest);
  1555.         }
  1556.         else
  1557.         {
  1558.             ThisBuffer -> IsBusy                    = TRUE;
  1559.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  1560.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  1561.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  1562.  
  1563.             ClrSignal(SIG_SERWRITE);
  1564.             SendIO(ThisBuffer -> SerialRequest);
  1565.  
  1566.             *NextBuffer -> SerialIndex++ = c;
  1567.         }
  1568.     }
  1569. }
  1570.  
  1571.     /* com_purge(VOID):
  1572.      *
  1573.      *    Clear the read/write buffers.
  1574.      */
  1575.  
  1576. VOID
  1577. com_purge(VOID)
  1578. {
  1579.     if(ThisBuffer -> IsBusy)
  1580.     {
  1581.         if(!CheckIO(ThisBuffer -> SerialRequest))
  1582.             AbortIO(ThisBuffer -> SerialRequest);
  1583.  
  1584.         WaitIO(ThisBuffer -> SerialRequest);
  1585.     }
  1586.  
  1587.     ThisBuffer -> IsBusy        = FALSE;
  1588.     ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  1589.  
  1590.     NextBuffer -> IsBusy        = FALSE;
  1591.     NextBuffer -> SerialIndex    = NextBuffer -> SerialBuffer;
  1592.  
  1593.     if(ReadBuffer -> IsBusy)
  1594.     {
  1595.         if(!CheckIO(ReadBuffer -> SerialRequest))
  1596.             AbortIO(ReadBuffer -> SerialRequest);
  1597.  
  1598.         WaitIO(ReadBuffer -> SerialRequest);
  1599.     }
  1600.  
  1601.     ReadBuffer -> IsBusy        = FALSE;
  1602.     ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1603.     ReadBuffer -> SerialFilled    = 0;
  1604.  
  1605.     ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_CLEAR;
  1606.     DoIO(ThisBuffer -> SerialRequest);
  1607. }
  1608.  
  1609.     /* com_dump(VOID):
  1610.      *
  1611.      *    Wait for asynchronous write request to terminate.
  1612.      */
  1613.  
  1614. VOID
  1615. com_dump(VOID)
  1616. {
  1617.     com_flush();
  1618. }
  1619.  
  1620.     /* com_getbyte(VOID):
  1621.      *
  1622.      *    Read a single byte from the serial line. If not available,
  1623.      *    return EOF.
  1624.      */
  1625.  
  1626. int
  1627. com_getbyte(VOID)
  1628. {
  1629.     int Result;
  1630.  
  1631.     if(ReadBuffer -> SerialFilled <= 0)
  1632.     {
  1633.         if(ReadBuffer -> IsBusy)
  1634.         {
  1635.             if(!CheckIO(ReadBuffer -> SerialRequest))
  1636.                 return(EOF);
  1637.             else
  1638.                 WaitIO(ReadBuffer -> SerialRequest);
  1639.  
  1640.             ReadBuffer -> IsBusy        = FALSE;
  1641.             ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1642.             ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1643.  
  1644.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1645.  
  1646.             DoIO(ReadBuffer -> SerialRequest);
  1647.  
  1648.             if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1649.             {
  1650.                 LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  1651.  
  1652.                 if(Size > 0)
  1653.                 {
  1654.                     if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1655.                         Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1656.  
  1657.                     ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1658.                     ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  1659.                     ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  1660.  
  1661.                     DoIO(ReadBuffer -> SerialRequest);
  1662.  
  1663.                     ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1664.                 }
  1665.             }
  1666.         }
  1667.         else
  1668.         {
  1669.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  1670.  
  1671.             DoIO(ReadBuffer -> SerialRequest);
  1672.  
  1673.             if(!ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1674.                 return(EOF);
  1675.             else
  1676.             {
  1677.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1678.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer;
  1679.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = MIN(ReadBuffer -> SerialRequest -> IOSer . io_Actual,ReadBuffer -> SerialSize);
  1680.  
  1681.                 DoIO(ReadBuffer -> SerialRequest);
  1682.  
  1683.                 if(!ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1684.                     return(EOF);
  1685.                 else
  1686.                 {
  1687.                     ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1688.                     ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1689.                 }
  1690.             }
  1691.         }
  1692.     }
  1693.  
  1694.     Result = *ReadBuffer -> SerialIndex++;
  1695.  
  1696.     ReadBuffer -> SerialFilled--;
  1697.  
  1698.     if(ReadBuffer -> SerialFilled <= 0)
  1699.     {
  1700.         ReadBuffer -> IsBusy                    = TRUE;
  1701.         ReadBuffer -> SerialIndex                = ReadBuffer -> SerialBuffer;
  1702.  
  1703.         ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1704.         ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer;
  1705.         ReadBuffer -> SerialRequest -> IOSer . io_Length    = 1;
  1706.  
  1707.         ClrSignal(SIG_SERREAD);
  1708.         SendIO(ReadBuffer -> SerialRequest);
  1709.     }
  1710.  
  1711.     return(Result);
  1712. }
  1713.  
  1714.     /* setstamp(STRPTR Name,LONG Time):
  1715.      *
  1716.      *    Set time/date of a file.
  1717.      */
  1718.  
  1719. VOID
  1720. setstamp(char *Name,long Time)
  1721. {
  1722.         struct tm *t;
  1723.     struct ClockData ClockData;
  1724.     ULONG Seconds;
  1725.     struct DateStamp Date;
  1726.  
  1727.         t = localtime(&Time);
  1728.  
  1729.     ClockData . sec        = t -> tm_sec;
  1730.     ClockData . min        = t -> tm_min;
  1731.     ClockData . hour    = t -> tm_hour;
  1732.     ClockData . mday    = t -> tm_mday;
  1733.     ClockData . month    = t -> tm_mon;
  1734.     ClockData . year    = t -> tm_year + 1900;
  1735.  
  1736.     Seconds = Date2Amiga(&ClockData);
  1737.  
  1738.     Date . ds_Days        = Seconds / (24 * 60 * 60);
  1739.     Date . ds_Minute    = (Seconds % (24 * 60 * 60)) / 60;
  1740.     Date . ds_Tick        = (Seconds % 60) * TICKS_PER_SECOND;
  1741.  
  1742.     SetFileDate(Name,&Date);
  1743. }
  1744.  
  1745.     /* freespace(STRPTR DrivePath):
  1746.      *
  1747.      *    Get free disk space for specified drive.
  1748.      */
  1749.  
  1750. long
  1751. freespace(char *DrivePath)
  1752. {
  1753.     struct DevProc    *DevProc = GetDeviceProc(DrivePath,NULL);
  1754.     struct DosList    *DosList;
  1755.     BOOL         GoodDevice = FALSE;
  1756.     LONG         Size = (LONG)((ULONG)~0 >> 2);
  1757.  
  1758.     if(DosList = LockDosList(LDF_DEVICES | LDF_READ))
  1759.     {
  1760.         while(DosList = NextDosEntry(DosList,LDF_DEVICES))
  1761.         {
  1762.             if(DosList -> dol_Task == DevProc -> dvp_Port)
  1763.             {
  1764.                 struct FileSysStartupMsg *FSSM = (struct FileSysStartupMsg *)BADDR(DosList -> dol_misc . dol_handler . dol_Startup);
  1765.  
  1766.                 if(TypeOfMem(FSSM))
  1767.                 {
  1768.                     struct DosEnvec *DosEnvec = (struct DosEnvec *)BADDR(FSSM -> fssm_Environ);
  1769.                     STRPTR Name = (STRPTR)BADDR(FSSM -> fssm_Device);
  1770.  
  1771.                     if(TypeOfMem(DosEnvec) && TypeOfMem(Name))
  1772.                     {
  1773.                         if(Name[0] > 0 && !Name[(WORD)Name[0] + 1])
  1774.                         {
  1775.                             struct IOStdReq __aligned IORequest;
  1776.  
  1777.                             if(!OpenDevice(Name + 1,FSSM -> fssm_Unit,&IORequest,FSSM -> fssm_Unit))
  1778.                             {
  1779.                                 CloseDevice(&IORequest);
  1780.  
  1781.                                 if(DosEnvec -> de_TableSize > 0 && DosEnvec -> de_LowCyl <= DosEnvec -> de_HighCyl)
  1782.                                     GoodDevice = TRUE;
  1783.                             }
  1784.                         }
  1785.                     }
  1786.                 }
  1787.             }
  1788.         }
  1789.  
  1790.         UnLockDosList(LDF_DEVICES | LDF_READ);
  1791.     }
  1792.  
  1793.     FreeDeviceProc(DevProc);
  1794.  
  1795.     if(GoodDevice)
  1796.     {
  1797.         struct InfoData *InfoData;
  1798.  
  1799.         if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY | MEMF_PUBLIC))
  1800.         {
  1801.             UBYTE NewName[256],*Index;
  1802.             BPTR FileLock;
  1803.  
  1804.             memcpy(NewName,DrivePath,255);
  1805.  
  1806.             NewName[255] = 0;
  1807.  
  1808.             Index = PathPart(NewName);
  1809.  
  1810.             *Index = 0;
  1811.  
  1812.             FileLock = Lock(NewName,ACCESS_READ);
  1813.  
  1814.             if(FileLock)
  1815.             {
  1816.                 if(Info(FileLock,InfoData))
  1817.                     Size = InfoData -> id_BytesPerBlock * (InfoData -> id_NumBlocks - InfoData -> id_NumBlocksUsed);
  1818.  
  1819.                 UnLock(FileLock);
  1820.             }
  1821.  
  1822.             FreeVec(InfoData);
  1823.         }
  1824.     }
  1825.  
  1826.     return(Size);
  1827. }
  1828.  
  1829.     /* ffirst(char *FileSpec):
  1830.      *
  1831.      *    Return name of first file matching the given specs.
  1832.      */
  1833.  
  1834. char *
  1835. ffirst(char *filespec)
  1836. {
  1837.     AnchorUsed = TRUE;
  1838.  
  1839.     if(MatchFirst(filespec,Anchor))
  1840.         return(NULL);
  1841.     else
  1842.         return((char *)Anchor -> ap_Buf);
  1843. }
  1844.  
  1845.     /* fnext(VOID):
  1846.      *
  1847.      *    Return name of next file matching the given specs.
  1848.      */
  1849.  
  1850. char *
  1851. fnext(VOID)
  1852. {
  1853.     AnchorUsed = TRUE;
  1854.  
  1855.     if(MatchNext(Anchor))
  1856.         return(NULL);
  1857.     else
  1858.         return((char *)Anchor -> ap_Buf);
  1859. }
  1860.